package com.woniu.repaircenter.service.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.exception.XinanException;
import com.woniu.exception.repaircenter.RepaircenterException;
import com.woniu.repaircenter.models.dto.RepairFileUploadDTO;
import com.woniu.repaircenter.service.mapper.RepairFileUploadMapper;
import com.woniu.repaircenter.service.model.RepairFileUpload;
import com.woniu.repaircenter.service.service.RepairFileUploadService;
import com.woniu.utils.AliyunOSSUtil;
import com.woniu.utils.EnumException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 维修文件上传表 服务实现类
 *
 * @author 吕雨泽
 * @since 2024年12月06日
 */
@Service
@Validated
public class RepairFileUploadServiceImpl extends ServiceImpl<RepairFileUploadMapper, RepairFileUpload> implements RepairFileUploadService {

    @Autowired
    private RepairFileUploadMapper repairFileUploadMapper;

    @Autowired
    private AliyunOSSUtil aliyunOSSUtil;

    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB

    /**
     * 上传图片到阿里云OSS，并将图片信息存储到数据库中
     *
     * @param files    图片文件数组
     * @param userName 上传用户的用户名
     * @return 上传成功的文件ID集合
     * @throws IOException 如果上传过程中发生错误，抛出异常
     */
    @Override
    public Set<RepairFileUploadDTO> uploadImage(MultipartFile files, String userName) throws IOException, XinanException {
        Set<RepairFileUploadDTO> uploadedFileIds = new HashSet<>();
        validateFile(files);
        String originalFilename = files.getOriginalFilename();
        String suffix = StringUtils.getFilenameExtension(originalFilename);
        String prefix = UUID.randomUUID().toString();
        // 获取文件大小
        long fileSize = files.getSize();
        // 上传文件到阿里云OSS，并获取上传后的文件访问地址
        String imageUrl = aliyunOSSUtil.uploadFile(files.getInputStream(), prefix + "." + suffix, "woniuxy114-3-0");
        // 创建新的RepairFileUpload对象并设置属性
        RepairFileUpload repairFileUpload = new RepairFileUpload();
        repairFileUpload.setFilePath(imageUrl);
        repairFileUpload.setFileName(prefix);
        repairFileUpload.setFileSuffix(suffix);
        repairFileUpload.setSize(fileSize);
        repairFileUpload.setCreateUser(userName);
        repairFileUpload.setCreateTime(formatCurrentDateTime());
        // 将图片信息存储到数据库中
        Integer fileId = repairFileUploadMapper.insertFileUpload(repairFileUpload);
        RepairFileUploadDTO repairFileUploadDTO = new RepairFileUploadDTO();
        repairFileUploadDTO.setFilePath(imageUrl);
        repairFileUploadDTO.setRepairUploadId(repairFileUpload.getId().toString());
        // 添加上传成功的文件ID到集合中
        if (fileId != null) {
            uploadedFileIds.add(repairFileUploadDTO);
        }

        // 返回上传成功的文件ID集合
        return uploadedFileIds;
    }

    /**
     * 根据维修单号获取图片文件路径列表
     * @param repairUploadId 维修单号
     * @return 图片文件路径列表
     */
    @Override
    public List<String> getFilePathsByRepairUploadId(String repairUploadId) {
        List<String> filePaths = repairFileUploadMapper.getFilePath(repairUploadId);
        return filePaths != null ? filePaths : Collections.emptyList();
    }

    /**
     * 根据维修单号获取图片文件信息
     * @param set       图片文件ID集合
     * @param repairNum 维修单号
     * @return 添加结果
     */
    @Override
    @Transactional
    public Integer addFileUpload(Set<Integer> set, String repairNum) throws XinanException {
        try {
            // 调用数据库操作
            return repairFileUploadMapper.addFileUpload(set, repairNum);
        } catch (Exception e) {
            throw new RepaircenterException(EnumException.FILE_UPLOAD_FAILED);
        }
    }


/**
 * 删除图片

 * @param id 图片的ID，用于从数据库中定位要删除的图片记录
 * @throws XinanException 如果数据库中找不到对应的记录，或者阿里云OSS文件删除失败，或者数据库删除记录失败，抛出此异常
 */
@Override
public void deleteImage(Long id) throws XinanException {
    // 1. 从数据库中获取文件路径
    RepairFileUpload repairFileUpload = repairFileUploadMapper.selectById(id);
    if (repairFileUpload == null) {
        throw new XinanException(EnumException.DATABASE_ERROR);
    }

    String filePath = repairFileUpload.getFilePath();

    // 2. 从阿里云 OSS 中删除文件
    try {
        aliyunOSSUtil.deleteFile("woniuxy114-3-0", filePath);
    } catch (Exception e) {
        throw new XinanException(EnumException.PRODUCT_DELETE_FAILURE);
    }

    // 3. 从数据库中删除记录
    int result = repairFileUploadMapper.deleteById(id);
    if (result != 1) {
        throw new XinanException(EnumException.PRODUCT_DELETE_FAILURE);
    }
}



    /**
     * 验证文件格式和扩展名
     *
     * @param file 图片文件
     * @throws IOException 如果文件格式或扩展名不正确，抛出异常
     */
    private void validateFile(MultipartFile file) throws XinanException, IOException {
        try (InputStream inputStream = file.getInputStream()) {
            byte[] fileHeader = new byte[4];
            inputStream.read(fileHeader);
            String originalFilename = file.getOriginalFilename();

            if (originalFilename == null || !(AliyunOSSUtil.isJpg(fileHeader) || AliyunOSSUtil.isPng(fileHeader)) ||
                    (!originalFilename.toLowerCase().endsWith(".jpg") && !originalFilename.toLowerCase().endsWith(".png"))) {
                throw new RepaircenterException(EnumException.COMMENTUPLOADIMG_TYPE_EXCEPTION);
            }

            // 检查文件大小
            long fileSize = file.getSize();
            if (fileSize > MAX_FILE_SIZE) {
                throw new RepaircenterException(EnumException.FILE_SIZE_EXCEEDED);
            }
        }
    }

    /**
     * 格式化当前日期时间
     *
     * @return 格式化后的日期时间字符串
     */
    private String formatCurrentDateTime() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return LocalDateTime.now().format(formatter);
    }
}
